function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => {
    const t = setTimeout(() => {
      resolve();
      clearTimeout(t);
    }, ms);
  });
}

export default class StreamAudioPlayer {
  private audioContext: AudioContext;
  private playQueue: AudioBuffer[];
  private startTime: number;
  private nextSchedule: number;
  private state: { closed: boolean };

  constructor() {
    this.audioContext = new AudioContext();
    this.playQueue = []; // 待播放队列
    this.startTime = 0; // 播放起始时间
    this.nextSchedule = 0; // 下一个调度时间
    this.state = { closed: false };
  }

  private get closed(): boolean {
    return this.state.closed;
  }

  private set closed(v: boolean) {
    this.state.closed = v;
  }

  // 添加音频缓冲到队列
  async addAudioChunk(arrayBuffer: ArrayBuffer) {
    if (this.closed) {
      console.warn("StreamAudioPlayer has been closed.");
      return;
    }

    try {
      const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
      this.playQueue.push(audioBuffer);
    } catch (error) {
      console.error("音频解码失败:", error);
    }
  }

  // 播放调度
  async play() {
    while (this.playQueue.length === 0) {
      if (this.closed) {
        return;
      }
      await sleep(100);
    }

    const buffer = this.playQueue.shift();
    if (buffer) {
      const source = this.audioContext.createBufferSource();
      source.buffer = buffer;
      source.connect(this.audioContext.destination);

      // TODO: 这里需要理解
      // 精确计算播放时间
      if (this.nextSchedule === 0) {
        this.startTime = this.audioContext.currentTime;
        this.nextSchedule = buffer.duration;
        source.start(this.startTime);
      } else {
        source.start(this.startTime + this.nextSchedule);
        this.nextSchedule += buffer.duration;
      }

      source.onended = () => {
        this.play();
      };
    }
  }

  async close() {
    this.closed = true;
    await this.audioContext.close();
  }
}
